package main

import (
	"context"
	"fmt"
	"github.com/gorilla/websocket"
	"github.com/spf13/viper"
	"github.com/streadway/amqp"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"log"
	"net/http"
	carpb "serve/car/api/gen/v1"
	"serve/car/car"
	"serve/car/dao"
	"serve/car/mq/amqpclt"
	"serve/car/sim"
	"serve/car/ws"
	"serve/settings"
	"serve/shared/server"
)

func main() {
	err := settings.Init()
	if err != nil {
		log.Fatalf(" settings.Init() %v", err)
	}

	logger, err := server.NewZapLogger()
	if err != nil {
		log.Fatalf("cannot create logger err %v", err)
	}

	c := context.Background()            // 建立一个content
	MongoClient, err := mongo.Connect(c, // 创建mongo连接
		options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%s@%s:%d",
			viper.GetString("mongodb.user"),
			viper.GetString("mongodb.password"),
			viper.GetString("mongodb.host"),
			viper.GetInt("mongodb.port"),
		)))

	if err != nil {
		logger.Fatal("mongo.Connect err", zap.Error(err))
	}

	dial, err := amqp.Dial(fmt.Sprintf("amqp://%s:%s@%s:%d/",
		viper.GetString("amqp.user"),
		viper.GetString("amqp.password"),
		viper.GetString("amqp.host"),
		viper.GetInt("amqp.port"),
	))
	if err != nil {
		logger.Fatal("amqp.Dial err", zap.Error(err))
	}

	exchange := "coolcar"
	publisher, err := amqpclt.NewPublisher(dial, exchange)
	if err != nil {
		logger.Fatal("amqpclt.NewPublisher err", zap.Error(err))
	}

	conn, err := grpc.Dial(fmt.Sprintf("%s:%d",
		viper.GetString("car.srv.host"),
		viper.GetInt("car.srv.port"),
	), grpc.WithInsecure()) // 车的客户端

	if err != nil {
		logger.Fatal("cannot connect car service", zap.Error(err))
	}

	subscriber, err := amqpclt.NewSubscriber(dial, exchange, logger)
	if err != nil {
		logger.Fatal(" amqpclt.NewSubscriber", zap.Error(err))
	}

	simCont := sim.Controller{
		CarService: carpb.NewCarServiceClient(conn),
		Subscriber: subscriber,
		Logger:     logger,
	}

	go simCont.RunSimulations(context.Background())

	u := &websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	http.HandleFunc("/ws", ws.Handle(u, subscriber, logger))
	go func() {
		logger.Info("HTTP server started websocket", zap.String("addr", ":9090"))
		logger.Sugar().Fatal(http.ListenAndServe(":9090", nil))
	}()

	err = server.RunGRPCServer(&server.GrpcConfig{
		Name: "car",
		Addr: viper.GetInt("car.srv.port"),
		RegisterFunc: func(server *grpc.Server) {
			carpb.RegisterCarServiceServer(server, &car.Service{ // 注册trip的Server
				Logger:    logger, // 将日志传入Server
				Mongo:     dao.NewMongo(MongoClient.Database(viper.GetString("mongodb.dbname"))),
				Publisher: publisher,
			})
		},
		Logger: logger,
	})

	if err != nil {
		logger.Fatal(" server.RunGRPCServer()", zap.Error(err))
	}
}
